<?php

namespace App\ClickHouse;

use App\Commons\SingleInstanceTrait;
use App\Datalog\ErrorLog;

class ClickHouseBase
{
    use SingleInstanceTrait;

    // 数据库对象
    protected $db = null;

    // 集群连接配置
    protected $config = 'connect';

    // 集群名字
    protected $cluster = 'ck_cluster';

    // 库名
    protected $database = '';

    // 表名
    protected $table = '';

    // 请求超时秒
    protected $timeout = 10;

    public function __construct()
    {
        $config = config("clickhouse.{$this->config}");
        // https://github.com/smi2/phpClickHouse
        $this->db = new \ClickHouseDB\Client($config);
        $this->db->useSession();
        $this->db->setTimeout($this->timeout);
        $this->db->setConnectTimeOut(5);
        $this->db->ping(true);

        // 设置数据库
        if ($this->database == '') {
            $this->database = config("clickhouse.database");
        }

        $this->db->database($this->database);

        // 设置sql字节长度，例如留存统计时间过长会导致sql非常长。
        $this->db->settings()->set('max_query_size', 100000000);
    }

    public function pingDb()
    {
        return $this->db->ping();
    }

    public function setDatabase($database)
    {
        $this->database = $database;
        $this->db->database($this->database);
    }

    public function setTable($table)
    {
        $this->table = $table;
    }

    public function setTimeout($time)
    {
        $this->timeout = $time;
        $this->db->setTimeout($this->timeout);
    }

    public function getDb()
    {
        return $this->db;
    }

    public function insert($data, $key)
    {
        $status = false;
        try {
            $this->db->insert($this->table, $data, $key);
            $status = true;
        } catch (\Throwable $e) {
            ErrorLog::getInstance()->addThrowable($e);
        }

        return $status;
    }

    public function optimize()
    {
        $this->db->setTimeout(120);
        $query = "OPTIMIZE TABLE {$this->table} ON CLUSTER {$this->cluster} FINAL";
        $stat  = $this->db->write($query);
        $this->db->setTimeout($this->timeout);
    }

    public function select($sql)
    {
        // 如果请求失败会直接抛出异常
        $stat = $this->db->select($sql);

        // 返回结果对象，可通过 $stat->rows() 获取数组
        return $stat;
    }

    public function selectAsync($sqls)
    {
        $stats = [];
        foreach ($sqls as $key => $sql) {
            $stats[$key] = $this->db->selectAsync($sql);
        }
        $this->db->executeAsync();

        // 返回多个结果对象，每个结果对象与 $sqls 键值一一对应
        return $stats;
    }

    public function showDatabase()
    {
        return $this->select('show databases');
    }

    public function write($query)
    {
        return $this->db->write($query);
    }

    public function createDb($dbname)
    {
        $query = "CREATE DATABASE IF NOT EXISTS {$dbname} ON CLUSTER {$this->cluster}";
        $this->write($query);
    }
}
